package com.yhy.wxzn.wcs.device.plc.siemens;
import com.yhy.wxzn.common.enums.WcsDeviceTypeEnums;
import com.yhy.wxzn.common.enums.WcsPlcPropertyTypeEnums;
import com.yhy.wxzn.common.utils.ListHelper;
import com.yhy.wxzn.wcs.entity.WcsDeviceInfo;
import com.yhy.wxzn.wcs.device.plc.bean.*;
import com.yhy.wxzn.wcs.entity.WcsPlcConfig;
import com.yhy.wxzn.wcs.entity.WcsPlcProperty;
import com.yhy.wxzn.wcs.service.IWcsDeviceInfoService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Auther: 97354
 * @Date: 2023/11/6 16:07
 * @Description: PlcServer
 * @Version 1.0.0
 */
@Component
@Slf4j
public class SiemensPlcServer {

    @Autowired
    private IWcsDeviceInfoService deviceInfoService;
    //驱动信息线程
    public static Map<String, SiemensPlcDriver> plcDriverMap = new ConcurrentHashMap<>();
    //提升机处理线程
    public static Map<Integer, SiemensHoistProtocol> hoistProtocolMap = new ConcurrentHashMap<>();
    //输送线处理线程
    public static Map<Integer, SiemensPlcProtocol> plcProtocolMap = new ConcurrentHashMap<>();


    public void initProtocol(WcsPlcConfig plc, Map<Integer, List<WcsPlcProperty>> propertyMap) {
        String plcIp = plc.getIp();//IP地址
        String plcName = plc.getPlcName();//PLC名称
        int serial = plc.getSerial();//系列
        int rack = plc.getRack();//机架号
        int slot = plc.getSlot();//插槽号
        SiemensPlcDriver siemensPlcDriver = new SiemensPlcDriver(plcIp,plcName,serial,rack,slot);
        propertyMap.entrySet().parallelStream().forEach(p -> {
            String deviceId = String.valueOf(p.getKey());
            WcsDeviceInfo deviceInfo = deviceInfoService.getById(p.getKey());
            //根据设备加载对应的点位到内存
            List<WcsPlcProperty> plcProperties = p.getValue();
            PlcDriverData driverData = siemensPlcDriver.driverData;
            //加载设备心跳点位到内存
            createHeartBeatMap(deviceId,driverData,plcProperties);
            //加载出入库口点位到内存
            createPortMap(deviceId,driverData,plcProperties);
            //加载输送线点位到内存
            createTransLineMap(deviceId,driverData,plcProperties);
            //加载提升机点位到内存
            createHoistMap(deviceId,driverData,plcProperties);
            plcDriverMap.put(plcName,siemensPlcDriver);
            //PLC驱动
            siemensPlcDriver.start();
            //提升机业务处理线程
            if(deviceInfo.getDeviceType().intValue() == WcsDeviceTypeEnums.ELV.getValue().intValue()){
                SiemensHoistProtocol siemensHoistProtocol = new SiemensHoistProtocol();
                siemensHoistProtocol.setPlcNo(plcName);
                siemensHoistProtocol.setDeviceCode(deviceInfo.getId());
                siemensHoistProtocol.siemensPlcDriver = SiemensPlcServer.plcDriverMap.get(plcName);
                hoistProtocolMap.put(deviceInfo.getId(), siemensHoistProtocol);
                siemensHoistProtocol.start();
            }
            //输送线业务处理线程
            if(deviceInfo.getDeviceType().intValue() == WcsDeviceTypeEnums.TSL.getValue().intValue()){
                SiemensPlcProtocol siemensPlcProtocol = new SiemensPlcProtocol(plcName);
                siemensPlcProtocol.siemensPlcDriver = SiemensPlcServer.plcDriverMap.get(plcName);
                plcProtocolMap.put(deviceInfo.getId(), siemensPlcProtocol);
                siemensPlcProtocol.start();
            }
        });
    }

    /**
     * 提升机点位
     * */
    private void createHoistMap(String deviceId, PlcDriverData driverData, List<WcsPlcProperty> plcProperties) {
        int typeDevice = WcsPlcPropertyTypeEnums.HOIST.getValue();
        List<WcsPlcProperty> list = ListHelper.where(plcProperties, m -> m.getType() == typeDevice);
        list.forEach(m -> {
            HoistPlc hoistPlc = new HoistPlc();
            BeanUtils.copyProperties(m, hoistPlc);
            hoistPlc.setDeviceId(deviceId);
            driverData.getHoistPlcMap().put(deviceId, hoistPlc);
        });
        /**
         * 一些特殊点位
         * */
        int typeCoord = WcsPlcPropertyTypeEnums.HOISTCOORD.getValue();
        List<WcsPlcProperty> listCoord = ListHelper.where(plcProperties, m -> m.getType() == typeCoord);
        listCoord.forEach(m -> {
            BasePlc coordPlc = new BasePlc();
            BeanUtils.copyProperties(m, coordPlc);
            coordPlc.setDeviceId(deviceId);
            driverData.getCoordPlcMap().put(m.getCoord(),coordPlc);
        });
    }

    private void createTransLineMap(String deviceId, PlcDriverData driverData, List<WcsPlcProperty> plcProperties) {
        int type = WcsPlcPropertyTypeEnums.TRANSLINE.getValue();
        List<WcsPlcProperty> list = ListHelper.where(plcProperties, m -> m.getType() == type);
        list.forEach(m -> {
            TransmissionPlc transmissionPlc = new TransmissionPlc();
            BeanUtils.copyProperties(m, transmissionPlc);
            transmissionPlc.setDeviceId(deviceId);
            driverData.getTransLinePlcMap().put(m.getCoord(), transmissionPlc);
        });
    }

    private void createPortMap(String deviceId, PlcDriverData driverData, List<WcsPlcProperty> plcProperties) {
        int type = WcsPlcPropertyTypeEnums.PORT.getValue();
        List<WcsPlcProperty> list = ListHelper.where(plcProperties, m -> m.getType() == type);
        list.forEach(m -> {
            PortPlc portPlc = new PortPlc();
            BeanUtils.copyProperties(m, portPlc);
            portPlc.setDeviceId(deviceId);
            driverData.getPortPlcMap().put(m.getCoord(), portPlc);
        });
    }

    /**
     * 心跳点位
     * */
    private void createHeartBeatMap(String deviceId, PlcDriverData driverData, List<WcsPlcProperty> plcProperties) {
        int type = WcsPlcPropertyTypeEnums.HEARTBEAT.getValue();
        List<WcsPlcProperty> list = ListHelper.where(plcProperties, m -> m.getType() == type);
        list.forEach(m -> {
            HeartBeatPlc heartBeatPlc = new HeartBeatPlc();
            BeanUtils.copyProperties(m, heartBeatPlc);
            heartBeatPlc.setDeviceId(deviceId);
            driverData.getHeartBeatPlcMap().put(deviceId,heartBeatPlc);
        });
    }
}
